package gnss

import (
	"dgo/goutils/utils"
	"sync/atomic"
)

var (
	YObsEpochRtcmDecoder_create_cnt int32 = 0
)

type YObsEpochRtcmDecoder struct {
	rtcmRaw           *Rtcm3RawBufDecoder
	epoch             *GnssYObsEpoch
	epochMsmN         int
	CopyRoughR        bool
	OutputMessageFunc func(s string, args ...interface{})
	OnRtcmDecodeErr   func(msgid uint16, err error)
	OnRtcmCrcFail     func(buf []byte, err error)
	OnRtcmDecodeBug   func(buf []byte, err error)

	/***
	  返回false则 不进行解码
	*/
	OnRtcmBuf func(msgid uint16, buf []byte) bool

	/**
	  checktype : 1, 非正常的完结, 0:有完结标志
	*/
	OnEpochFunc func(epoch *GnssYObsEpoch, checktype int)
}

func NewYObsEpochRtcmDecoder() *YObsEpochRtcmDecoder {
	rval := &YObsEpochRtcmDecoder{}
	rval.rtcmRaw = NewRtcm32RawBufDecoder("")
	rval.epoch = NewGnssYObsEpoch()
	rval.init()
	atomic.AddInt32(&YObsEpochRtcmDecoder_create_cnt, 1)
	return rval
}

func (this *YObsEpochRtcmDecoder) outputMessage(s string, args ...interface{}) {
	if this.OutputMessageFunc != nil {
		this.OutputMessageFunc(s, args)
	} else {
		utils.Log.Debugf(s, args...)
	}
}

func (this *YObsEpochRtcmDecoder) onEpoch(checktype int) {
	if this.OnEpochFunc != nil {
		this.OnEpochFunc(this.epoch, checktype)
	}
	this.epochMsmN = 0
}

func (this *YObsEpochRtcmDecoder) initEpoch(msm RtcmRawMsm) {
	this.epoch.Reset()
	this.epoch.TOW = msm.GetHeader().GetTOW()
	this.epoch.SmoothingInterval = msm.GetHeader().SmoothingInterval
	this.epoch.SmoothingType = msm.GetHeader().SmoothingType
	this.epoch.IODS = msm.GetHeader().IODS
	this.epoch.ClkSteering = msm.GetHeader().ClkSteering
	this.epoch.ExternalClk = msm.GetHeader().ExternalClk
	this.epoch.StaID = msm.GetHeader().StaID
}

func (this *YObsEpochRtcmDecoder) InputDone() {
	if this.epochMsmN > 0 {
		this.onEpoch(1)
	}
}

func (this *YObsEpochRtcmDecoder) onRtcmMsm(msm RtcmRawMsm) {
	if this.epochMsmN == 0 {
		this.initEpoch(msm)
	} else {
		if this.epoch.TOW != msm.GetHeader().GetTOW() {
			this.onEpoch(1)
			this.initEpoch(msm)
		}
	}
	YObsEpochFromRtcmMsm(this.epoch, msm, this.CopyRoughR)
	this.epochMsmN++
	if msm.GetHeader().EpochEndFlag {
		this.onEpoch(0)
	}
}

func (this *YObsEpochRtcmDecoder) init() {
	this.rtcmRaw.OnRtcmBuf = func(rtcmBuf []byte) {
		this.InputRtcmBuf(rtcmBuf)
	}
	this.rtcmRaw.OnErr = func(errcode int, err error) bool {
		if errcode == RTCM_CRC_FAIL {
			if this.OnRtcmCrcFail != nil {
				this.OnRtcmCrcFail(this.rtcmRaw.GetRawBuf(), err)
			} else {
				this.outputMessage("%s", err.Error())
			}
		} else if errcode == RTCM_BUG_DATA {
			if this.OnRtcmDecodeBug != nil {
				this.OnRtcmDecodeBug(this.rtcmRaw.GetRawBuf(), err)
			}
		}
		return true
	}
}

func (this *YObsEpochRtcmDecoder) InputBuf(buf []byte) {
	this.rtcmRaw.InputBuf(buf)
}

/*
*

	rtcmBuf 包含头和CRC
*/
func (this *YObsEpochRtcmDecoder) InputRtcmBuf(rtcmBuf []byte) {
	msgid := uint16(GetRtcmMsgId(rtcmBuf, 24))
	if this.OnRtcmBuf != nil {
		if !this.OnRtcmBuf(uint16(msgid), rtcmBuf) {
			return
		}
	}

	if RtcmIsMsm4(msgid) {
		msm4 := NewRtcmRawMsm4()
		err := msm4.DecodeMsm(rtcmBuf)
		if err != nil {
			if this.OnRtcmDecodeErr != nil {
				this.OnRtcmDecodeErr(msgid, err)
			} else {
				this.outputMessage("[%s]%s", msgid, err.Error())
			}
		} else {
			this.onRtcmMsm(msm4)
		}
	} else if RtcmIsMsm7(msgid) {
		msm7 := NewRtcmRawMsm7()
		err := msm7.DecodeMsm(rtcmBuf)
		if err != nil {
			if this.OnRtcmDecodeErr != nil {
				this.OnRtcmDecodeErr(msgid, err)
			} else {
				this.outputMessage("[%s]%s", msgid, err.Error())
			}
		} else {
			this.onRtcmMsm(msm7)
		}
	}
}
